package controleur;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.filechooser.FileNameExtensionFilter;
import modele.Environnement;
import modele.EnvironnementTriangle;
import vue.Case;
import vue.CaseTriangle;
import vue.Fenetre;
import vue.FenetreOption;

/**
 *
 * @author marc
 */
public class Controleur {

    //Le controleur
    private Fenetre vue;
    private Environnement modele;

    public Controleur(Fenetre v, Environnement m) {
        vue = v;
        modele = m;

        eventCases();
        eventFenetre();
        eventMenu();
        eventSpinner();
        eventPlacer();
        modele.initCases();

    }

    private void eventCases() {
        final Case[][] tabCases = vue.getCases();
        for (int i = 0; i < vue.getLargeurGrille(); i++) {
            for (int y = 0; y < vue.getHauteurGrille(); y++) {
                final Case tmp = tabCases[i][y];
                final int largeur = i, hauteur = y;
                tabCases[i][y].addMouseListener(new MouseAdapter() {

                    @Override
                    public void mousePressed(MouseEvent arg0) {
                        super.mouseClicked(arg0);
                        if (modele.isPaused() || !modele.isStarted()) {
                            //Si on est en train de placer un motif
                            if (vue.getPlacer().getText() == "Terminer") {
                                //on envoie toute la grille au modele
                                boolean[][] tabVue = new boolean[vue.getLargeurGrille()][vue.getHauteurGrille()];
                                for (int x = 0; x < vue.getLargeurGrille(); x++) {
                                    for (int z = 0; z < vue.getHauteurGrille(); z++) {
                                        if(vue.getForme() == vue.CARRE)
                                        {
                                        if (tabCases[x][z].getBackground() == Color.YELLOW || tabCases[x][z].getBackground() == Color.GREEN) {
                                            tabVue[x][z] = true;
                                        } else {
                                            tabVue[x][z] = false;
                                        }
                                        }
                                        else
                                        {
                                            CaseTriangle t = (CaseTriangle) tabCases[x][z];
                                            if(t.getColor() == Color.YELLOW || t.getColor() == Color.GREEN)
                                            {
                                                tabVue[x][z] = true;
                                            }
                                            else
                                                tabVue[x][z] = false;
                                                
                                        }
                                    }
                                }
                                modele.setCases(tabVue);
                            } else {
                                
                                if (tmp.isOpaque()) {
                                    
                                    if (tmp.getBackground() == Color.GREEN) {
                                        tmp.setBackground(Color.WHITE);
                                        modele.getCases()[largeur][hauteur].setEtat(false);
                                    } else {
                                        tmp.setBackground(Color.GREEN);
                                        modele.getCases()[largeur][hauteur].setEtat(true);
                                    }
                                } else {
                                    CaseTriangle t = (CaseTriangle) tmp;
                                    if(t.getColor() == Color.WHITE){
                                        t.setColor(Color.GREEN);
                                         modele.getCases()[largeur][hauteur].setEtat(true);
                                    }
                                    else{
                                        t.setColor(Color.WHITE);
                                         modele.getCases()[largeur][hauteur].setEtat(false);
                                    }
                                    t.repaint();
                                    
                                }
                            }
                        }
                    }

                    public void mouseEntered(MouseEvent arg0) {
                        super.mouseClicked(arg0);
                        int hauteurMotif = 0;
                        int largeurMotif = 0;
                        //si on a cliqué sur placer
                        if (vue.getPlacer().getText() == "Terminer") {
                            FileReader f = null;
                            try {
                                f = new FileReader("motif/" + (String) vue.getListeMotif().getSelectedItem() + ".jdlv");
                            } catch (FileNotFoundException ex) {
                                Logger.getLogger(Controleur.class.getName()).log(Level.SEVERE, null, ex);
                            }
                            //lecture du motif
                            BufferedReader bf = new BufferedReader(f);
                            try {
                                hauteurMotif = Integer.parseInt(bf.readLine());
                                largeurMotif = Integer.parseInt(bf.readLine());

                                for (int z = hauteur; z < hauteur + hauteurMotif; z++) {
                                    for (int x = largeur; x < largeur + largeurMotif; x++) {
                                        if (x < vue.getLargeurGrille() && z < vue.getHauteurGrille()) {
                                            if (bf.read() == '1') {
                                                if(vue.getForme() == vue.CARRE)
                                                    tabCases[x][z].setBackground(Color.YELLOW);
                                                else
                                                {
                                                    CaseTriangle t = (CaseTriangle) tabCases[x][z];
                                                    t.setColor(Color.YELLOW);
                                                    t.repaint();
                                                }
                                                    
                                            } else {
                                                if(vue.getForme() == vue.CARRE)
                                                    tabCases[x][z].setBackground(Color.WHITE);
                                                else
                                                {
                                                    CaseTriangle t = (CaseTriangle) tabCases[x][z];
                                                    t.setColor(Color.WHITE);
                                                    t.repaint();
                                                }
                                            }
                                        } else {
                                            bf.read();
                                        }

                                    }
                                    bf.read();
                                }
                                bf.close();
                                f.close();
                            } catch (IOException ex) {
                                Logger.getLogger(Controleur.class.getName()).log(Level.SEVERE, null, ex);
                            }

                        }
                    }

                    @Override
                    public void mouseExited(MouseEvent arg0) {
                        super.mouseExited(arg0);
                        //Si on est en train de placer un motif, si on sort de la case sans cliquer on remet la "bonne"
                        //grille
                        if (vue.getPlacer().getText() == "Terminer") {
                            modele.resend();
                        }

                    }

                });
            }
        }
    }

    private void eventFenetre() {
        vue.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent arg0) {
                super.windowClosing(arg0);
                System.exit(0);
            }
        });
        eventInit();
        eventClean();
        eventStart();
        eventPause();
    }

    private void eventStart() {
        vue.getStart().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (!modele.isStarted()) {
                    modele.start();
                } else {
                    modele.reprendre();
                }
                vue.getInit().setEnabled(false);
                vue.getPause().setEnabled(true);
                vue.getStart().setEnabled(false);
                vue.getClean().setEnabled(false);
                vue.getPlacer().setEnabled(false);
                vue.getPlacer().setText("Placer");
            }
        });
    }

    private void eventPause() {
        vue.getPause().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (modele.isPaused()) {
                    vue.getInit().setEnabled(false);
                    vue.getClean().setEnabled(false);
                    vue.getPause().setText("Pause");
                    vue.getPlacer().setEnabled(false);
                    vue.getPlacer().setText("Placer");
                    modele.reprendre();
                } else {
                    vue.getInit().setEnabled(true);
                    vue.getClean().setEnabled(true);
                    vue.getPause().setText("Reprendre");
                    vue.getPlacer().setEnabled(true);
                    modele.pause();
                }
            }
        });
    }

    private void eventInit() {
        vue.getInit().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                modele.initCases();
                //si on est en pause
                if (modele.isPaused()) {
                    vue.setButtonsDefault();
                }

            }
        });
    }

    private void eventClean() {
        vue.getClean().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                modele.clearCases();
                //si on est en pause
                if (modele.isPaused()) {
                    vue.setButtonsDefault();
                }

            }

        });
    }

    private void eventMenu() {
        eventOuvrir();
        eventSauvegarder();
        eventQuitter();
        eventOptions();
    }

    private void eventOuvrir() {
        vue.getOpen().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                modele.pause();
                JFileChooser chooser = new JFileChooser();
                FileNameExtensionFilter filter = new FileNameExtensionFilter(
                        "Jeu de la vie", "jdlv");
                chooser.setFileFilter(filter);
                int returnVal = chooser.showOpenDialog(vue);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    modele.open(chooser.getSelectedFile().getAbsolutePath());
                }
                vue.setButtonsDefault();
                eventCases();
            }
        });
    }

    private void eventSauvegarder() {
        vue.getSave().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                modele.pause();
                JFileChooser chooser = new JFileChooser();
                chooser.setDialogTitle("Sauvegarder");
                FileNameExtensionFilter filter = new FileNameExtensionFilter(
                        "Jeu de la vie", "jdlv");

                chooser.setFileFilter(filter);
                int returnVal = chooser.showOpenDialog(vue);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    if (chooser.getSelectedFile().getAbsolutePath().endsWith(".jdlv")) {
                        modele.save(chooser.getSelectedFile().getAbsolutePath());
                    } else {
                        modele.save(chooser.getSelectedFile().getAbsolutePath() + ".jdlv");
                    }
                    JOptionPane.showMessageDialog(vue, "Jeu sauvegardé");
                }
                if (!vue.getStart().isEnabled()) {
                    vue.getPause().setText("Reprendre");
                }

            }
        });
    }

    private void eventQuitter() {
        vue.getQuit().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
    }

    private void eventOptions() {
        vue.getOptions().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                FenetreOption op = new FenetreOption(vue, vue.getLargeurGrille(), vue.getHauteurGrille(), vue.getForme());
                eventOptionsValider(op);
                eventOptionsAnnuler(op);
                op.setVisible(true);
            }

        });
    }

    private void eventOptionsValider(final FenetreOption op) {
        op.getValider().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                modele.pause();
                
                vue.setForme(op.getForme());
                if(op.getForme() == vue.CARRE)
                {
                    modele = new Environnement(op.getHauteur(), op.getLargeur());
                    vue.getSpinTemps().setValue(1000);
                }
                else
                {
                    modele = new EnvironnementTriangle(op.getHauteur(), op.getLargeur());
                    vue.getSpinTemps().setValue(1000);
                }
                
                Integer[] size = new Integer[2];
                size[0] = op.getLargeur();
                size[1] = op.getHauteur();
                vue.setModele(modele);
                vue.resizeGrille(size);
                vue.setButtonsDefault();
                eventCases();
                op.setVisible(false);
            }

        });
    }

    private void eventOptionsAnnuler(final FenetreOption op) {
        op.getAnnuler().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                op.setVisible(false);
            }

        });
    }

    private void eventSpinner() {
        vue.getSpinTemps().addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                modele.changeIntervalle((int) vue.getSpinTemps().getValue());
            }

        });
    }

    private void eventPlacer() {
        vue.getPlacer().addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (modele.isPaused() || !modele.isStarted()) {
                    if (vue.getPlacer().getText() == "Terminer") {
                        vue.getPlacer().setText("Placer");
                    } else {
                        vue.getPlacer().setText("Terminer");
                    }
                }
            }
        });
    }

    public void start() {
        vue.setVisible(true);
        
    }
}
